你可能聽過有人把Base64當作資料庫密碼加密來用這樣的鬼故事,記住它只是改變字串表示方式,改變字串表示方式,改變字串表示方式,很重要所以說三次。
我們必須先回到電腦最底層的現實:電腦只看得懂 0 與 1,根本不認識文字。
我們在 Java 程式中寫下的任何字串(例如 "Hello" 或 "哈囉"),都必須先透過 文字編碼 (Character Encoding) 翻譯成一串數字(byte[]),電腦才能儲存或處理。
A 的 ASCII 碼是 65 / 0x41)。Java 的 String 是 Unicode 字元序列,密碼學 API 多半接收 byte[]。從字串轉成位元組必須明確指定 UTF-8,否則不同平台預設 charset 可能產生不同結果。
// 錯誤作法:直接調用getBytes()會使用作業系統預設的編碼 Linux 上可能是 UTF-8,但在 Windows 上可能是 CP950 (Big5)
// 這會導致相同的程式碼在不同作業系統跑出完全不同的 byte[]!
byte[] dangerousBytes = "哈囉".getBytes();
// 正確做法:永遠明確指定 StandardCharsets.UTF_8
byte[] safeBytes = "哈囉".getBytes(StandardCharsets.UTF_8);
0-9, a-f)表示。
A-Z, a-z, 0-9, +, /)。不足 3 Bytes 時尾端補 =。+ 換成 -,/ 換成 _,並去掉尾端的 =,避免在 URL 中被網頁伺服器誤判。-----BEGIN PUBLIC KEY----- 後面的內容)、JWT Token、API 加密欄位傳輸。String original = "密碼";
byte[] utf8 = original.getBytes(StandardCharsets.UTF_8);
String base64 = Base64.getEncoder().encodeToString(utf8);
String base64url = Base64.getUrlEncoder().encodeToString(utf8);
String hex = HexFormat.of().withUpperCase().withDelimiter(" ").formatHex(utf8);
String restored = new String(
Base64.getDecoder().decode(base64), StandardCharsets.UTF_8);
System.out.println("Base64: " + base64);//5a+G56K8
System.out.println("Base64url: " + base64url);//5a-G56K8
System.out.println("Hex: " + hex);//E5 AF 86 E7 A2 BC
System.out.println("Restored equals original: " + restored.equals(original));
文字經過 UTF-8 轉成 byte[] 後,就能交給 AES 或 RSA 進行加密運算。
但這裡會有一個新問題:加解密與雜湊運算出來的結果,是完全隨機的二進位陣列 (byte[])。
這意味著每一顆 Byte 都有可能出現 x00 ~ xFF(256 種組合)中的任意數值,包含大量的控制字元(如 0x00 Null、0x0A 換行)或 UTF-8 無法識別的非法片段。
如果直接將密文 byte[] 硬轉回 UTF-8 字串(例如 new String(cipherBytes, StandardCharsets.UTF_8)),UTF-8 引擎會因為無法解析而直接塗改毀損資料(替換成 ``),導致解密必定失敗!
為了將這些亂七八糟的二進位密文安全地放入 HTTP Header、JSON、URL 或資料庫中,我們需要第二層轉碼——將二進位編碼為安全的 ASCII 純文字。